#!/usr/bin/env python

# A Little Luxury Consignment Software
# Author: Justin Sweitzer, justin.c.sweitzer@gmail.com
# Open Source Software
# Distributed under the MIT License
#    A Little Luxury Consignment Boutique, LLC
#    7914 Memorial Parkway SW
#    Huntsville, AL 35803
#    256-970-4117


import sys, os, time, shutil
import subprocess as sp
import datetime
from Tkinter import *

sys.path.append('Software')
import add_consignor, add_item, generate_reports, generate_receipt, generate_barcodes, search_inventory
import view_inventory, view_consignor, complete_sale, consignor_totals, data_handler 

def initialize():
    if not os.path.exists('.consignment'):
        

        f = open('.consignment','w')
        f.writelines('softwarePath=./Software\n')
        f.writelines('taxRate=0.09\n')
        f.writelines('consPeriod=90\n')
        f.writelines('storePath=./Store\n')
        f.writelines('backupPath=./.backups\n')
        f.writelines('consignorSplit=0.6\n')
        f.close()
        
    f = open('.consignment','r')
    params = f.readlines()
    f.close()
    for line in params:
        if 'taxRate=' in line:
            taxRate = float(line.strip().split('=')[1])
        elif 'consPeriod' in line:
            consPeriod = int(line.strip().split('=')[1])
        elif 'backupPath' in line:
            backupPath = line.strip().split('=')[1]
        elif 'softwarePath' in line:
            softwarePath = line.strip().split('=')[1]
        elif 'storePath' in line:
            storePath = line.strip().split('=')[1]
        elif 'consignorSplit' in line:
            consignorSplit = float(line.strip().split('=')[1])

    return(taxRate,consPeriod,backupPath,storePath,softwarePath,consignorSplit)
        

class main():
    def __init__(self, root):        
        
        
        self.initVars()
        self.mainGui()
        self.sideBarGui()

        
    def lookupItem(self,event=None):
        bcode = self.readBarcode.get()
        if bcode != '':
            booth, item, price = bcode.split()
            sale_item = self.dh.get_item(booth,item,price)
            saleList_entry = '%s %s %s: %s  $%s' % (sale_item.owner_number, sale_item.item_number ,sale_item.owner,sale_item.description,sale_item.original_price) 
            self.current_sale.append(sale_item)     #booth,item,consignor,description,price
            self.saleList.insert(END,saleList_entry)
            self.readBarcode.set('')
            self.updateTotals(float(sale_item.original_price))
            self.focalPoint.focus()
                
    def updateTotals(self, price):
        if self.saleMethod.get() == 2:
            taxRate = 0
        elif self.saleMethod.get() == 1:
            taxRate = self.taxRate

        self.subTotal += price
        self.taxTotal = taxRate*self.subTotal
        self.ovrTotal = self.subTotal+self.taxTotal
        self.totalLabelVar.set('Subtotal: $%.2f, Tax: $%.2f, Total: $%.2f' % (self.subTotal, self.taxTotal, self.ovrTotal))
        
        
    def completeSale(self):
        timestamp = time.localtime()
        transactionTime = time.asctime()
        receipt = os.path.join(self.receiptPath,'%s.pdf' % transactionTime.replace(' ','_').replace(':','-'))
        top = Toplevel()
        sale_list = []
        for item in self.current_sale:
            
            if item.type is not 'null_item':
                sale_list.append([item.owner_number,item.item_number,item.owner,item.description,item.sale_price])
                
        tendered = complete_sale.main(self.subTotal,self.taxTotal,self.ovrTotal,sale_list, receipt,top, self)
        self.root.wait_window(tendered.root)
        
        if not os.path.exists('.backups'):
            os.mkdir('.backups')

        if os.path.exists(receipt):
        
            for item in self.current_sale:
                if item.type is not 'null_item':
                    if self.saleMethod.get() == 1:
                        item.sale_location = 'In store'
                    elif self.saleMethod.get() == 2:
                        item.sale_location = 'Internet'
                    item.sell()
                    
            reportName = os.path.join(self.salesPath, '%s_%s_Sales.csv' % (timestamp.tm_mon, timestamp.tm_year))                
            f = open(reportName,'a')
            for item in self.current_sale:
                if item.type is not 'null_item':
                    f.writelines('%s,%s,%s,%s,%s,%s\n' % (transactionTime,item.owner_number,item.item_number,item.owner,item.description,item.sale_price))
                f.writelines('END OF SALE, SUBTOTAL:,%.2f, TAX:,%.2f, TOTAL:,%.2f\n' % (self.subTotal,self.taxTotal,self.ovrTotal))
            f.close()     
                
            shutil.copy(reportName, os.path.join(self.backupPath,'%s_%s.csv' % (timestamp.tm_mon, timestamp.tm_year)))
            self.emptyCart()
            self.readBarcode.set('')
            self.focalPoint.focus()
            sp.call(['gnome-open',receipt])

              
    def deleteSaleItem(self,anchors):
        
        for anchor in anchors:
            anchor = int(anchor)
            item = self.current_sale[anchor]
            price = item.sale_price
            price = float(price)
            item.sale_price = item.original_price
            
            self.current_sale.pop(anchor)
            self.updateTotals(-1*price)
            self.saleList.delete(anchor)
            self.readBarcode.set('')
        self.focalPoint.focus()            
        
    def emptyCart(self):
        self.subTotal = 0
        self.taxTotal = 0
        self.ovrTotal = 0
        self.totalLabelVar.set('Subtotal: $%.2f, Tax: $%.2f, Total: $%.2f' % (self.subTotal, self.taxTotal, self.ovrTotal))
        self.saleList.delete(0,END)
        self.current_sale = []
        self.readBarcode.set('')
        self.focalPoint.focus()
        
    def viewInventory(self):
        top = Toplevel()
        view_inventory.start(self,top)
    
    def lookupConsignor(self):
        top = Toplevel()
        view_consignor.start(self,top)
    
    def genReports(self):
        generate_reports.start(self)
    
    def addConsignor(self):
        top = Toplevel()
        add_consignor.start(self,top)
    
    def addInventory(self):
        top = Toplevel()
        add_item.start(self,top)
    
    def searchInventory(self):
        top = Toplevel()
        search_inventory.start(self,top)
        
    def genBarcodes(self):
        top = Toplevel()
        generate_barcodes.start(self,top)
        
    def consignorTotals(self):
        top = Toplevel()
        consignor_totals.start(self,top)

    def checkConsigmentPeriods(self):
        today = datetime.date.today()
        chkfile = os.path.join(self.reportPath, 'ConsignmentPeriod_TimeLeft.csv')
        
        f = open(chkfile,'w')
        f.writelines('consignor,description,price,consign date, days left\n') 
        for key in self.dh.cons_dict.keys():
            cons = self.dh.cons_dict[key]
            for item_key in cons.item_dict.keys():
                item = cons.item_dict[item_key]
                
                consignor, description, price = cons.full_name,item.description,item.original_price
                cons_date=item.consign_date
                print cons_date
                try:
                    date_format = "%m/%d/%Y"
                    cons_date = datetime.datetime.strptime(cons_date, date_format)
                except ValueError:
                    date_format = "%m/%d/%y"
                    cons_date = datetime.datetime.strptime(cons_date, date_format)
                
                cons_date = datetime.date(cons_date.year,cons_date.month,cons_date.day)
                diff = today - cons_date
                days_left = self.consPeriod-diff.days
                f.writelines('%s,%s,%s,%s,%i\n' % (consignor,description,price,cons_date,days_left))
        f.close()
        sp.call(['gnome-open',chkfile])
            
    def adjPrice(self,event=None):
        anchors = self.saleList.curselection()
        for anchor in anchors:
            anchor = int(anchor)
            sale_item = self.current_sale[anchor]
            consignor = sale_item.owner
            price = float(sale_item.sale_price)
            description = sale_item.description
            newprice = self.adjItemPrice.get()            
            sale_item.sale_price = newprice         
              
            pricediff = float(newprice) - price
            date = time.strftime('%m/%d/%Y')          
            newitem = '%s,%s,%.2f,%s' % (consignor,'Price Adj:'+description,pricediff,date)
            null_item=self.dh.add_null_item(pricediff)
            self.current_sale.append(null_item)
            self.saleList.insert(END,newitem)
            self.updateTotals(pricediff)
            self.focalPoint.focus()
            
    def discPrice(self,event=None):
        anchors = self.saleList.curselection()
        for anchor in anchors:
            anchor = int(anchor)
            item = self.saleList.get(anchor)    
            cur_sale_ent = self.current_sale[anchor]        
            consignor = cur_sale_ent.owner
            
            booth, item, description, price = cur_sale_ent.owner_number, cur_sale_ent.item_number, cur_sale_ent.description, cur_sale_ent.sale_price        
            price = float(price)
            newprice = price-(float(self.discItemPrice.get())*price)/100.
            cur_sale_ent.sale_price = '%.2f' % newprice
            pricediff = newprice - price
            date = time.strftime('%m/%d/%Y')           
            newitem = '%s,%s,%.2f,%s' % (consignor,'Price Adj:'+description,pricediff,date)
            null_item=self.dh.add_null_item(pricediff)
            self.current_sale.append(null_item)
            self.saleList.insert(END,newitem)
            self.updateTotals(pricediff)
            self.focalPoint.focus()

    def adjCart(self,event=None):            
        discpct = float(self.applyDiscountPct.get())
        discdol = -1.*discpct*self.subTotal/100.
        for sale_item in self.current_sale:
            if sale_item.type is not 'null_item':
                old_price = sale_item.sale_price
                new_price = float(old_price)*(1-discpct/100.)
                sale_item.sale_price = '%.2f' % new_price        
                
        null_item=self.dh.add_null_item(discdol)
        self.current_sale.append(null_item)
        date = time.strftime('%m/%d/%Y')
        newitem = 'Store Discount,%.1f Percent Discount,%.2f,%s' % (discpct,discdol,date)
        self.saleList.insert(END,newitem)
        self.updateTotals(discdol)
        self.focalPoint.focus()

    def initVars(self):
        self.root = root
        self.root.title('A Little Luxury')
        self.taxRate,self.consPeriod,self.backupPath,self.storePath,self.softwarePath, self.consignor_split = initialize()
        self.storeCreditPath = os.path.join(self.storePath,'StoreCredit')
        self.boothPath = os.path.join(self.storePath,'Booths')
        self.receiptPath = os.path.join(self.storePath,'Receipts')
        self.reportPath = os.path.join(self.storePath,'Reports')
        self.itemPath = os.path.join(self.storePath,'Items')
        self.barcodePath = os.path.join(self.storePath,'Barcodes')
        self.salesPath = os.path.join(self.storePath, 'Sales')
       
        allPaths = [ self.storePath, self.boothPath, self.receiptPath, self.reportPath, self.itemPath, self.barcodePath, self.salesPath, self.storeCreditPath ]
        for item in allPaths:
            if not os.path.exists(item):
                os.mkdir(item)
        self.dh = data_handler.store(self)
        self.mainframe = Frame(self.root,padx=12,pady=12 )         
        self.mainframe.grid(column=0, row=0, sticky = (N, W, E ,S))
        self.mainframe.columnconfigure(0, weight=1)
        self.mainframe.rowconfigure(0, weight=1)               
        self.sideframe = Frame(self.root,padx=4,pady=12)
        self.sideframe.grid(row=0,column=1)          
        self.readBarcode = StringVar()          
        self.adjItemPrice = StringVar()
        self.applyDiscountPct = StringVar()
        self.discItemPrice = StringVar()      
        self.totalLabelVar = StringVar()        
        self.lstVar = StringVar()               
        self.current_sale = []    
        self.subTotal = 0
        self.taxTotal = 0
        self.ovrTotal = 0        
        self.lstVar.set("Scan barcode and click 'Look up' to add items to sale")
        self.totalLabelVar.set('Subtotal: $%.2f, Tax: $%.2f, Total: $%.2f' % (self.subTotal, self.taxTotal, self.ovrTotal))
        

    def mainGui(self):
        self.saleList = Listbox(self.mainframe,width=80,height=30)
        self.saleList.grid(row=3,column=1,columnspan=6,sticky=W)
        totalLabel = Label(self.mainframe,textvariable=self.totalLabelVar).grid(row=5,column=1,columnspan=6,sticky=E)
        lstLabel = Label(self.mainframe,textvariable=self.lstVar).grid(row=4,column=1,columnspan=6,sticky=W)
        lstSellBtn = Button(self.mainframe, text='Sell',command=self.completeSale,width=14).grid(row=6,column=5,sticky=W)
        lstClearBtn = Button(self.mainframe, text='Clear All',command=self.emptyCart,width=14).grid(row=6,column=4,sticky=W)
        lstDeleteBtn = Button(self.mainframe, text='Delete One',command = lambda lb=self.deleteSaleItem: lb(self.saleList.curselection()),width=14)
        lstDeleteBtn.grid(row=6,column=3,sticky=W)       
        barcodeEntry = Entry(self.mainframe, width=20, textvariable=self.readBarcode)
        barcodeEntry.grid(row=1, column=1,columnspan=3, sticky=W)
        barcodeLabel = Label(self.mainframe, text= 'Scan barcode to look up item').grid(row=2,column=1,columnspan=4,sticky=W)        
        lkpButton = Button(self.mainframe, text='Look up', command=self.lookupItem,width=14).grid(row=1,column=4,sticky=E)
        barcodeEntry.bind('<Return>',self.lookupItem)
        barcodeEntry.bind('<KP_Enter>',self.lookupItem)
        
        self.saleMethod = IntVar()
        self.saleMethod.set(1)
        saleMethod = [('In store',1),('Internet',2)]
        i=5
        for text, mode in saleMethod:
            b = Radiobutton(self.mainframe, text=text, variable=self.saleMethod, value=mode)
            b.grid(row=2,column=i)
            i+=1   
        self.focalPoint = barcodeEntry
        self.focalPoint.focus()
    
    def sideBarGui(self):
        i = 0
        genReportsButton=Button(self.sideframe,text='Generate Reports',command=self.genReports,width=14).grid(row=i,column=0)
        i+=1
        genBarcodes = Button(self.sideframe,text='Make Barcodes',width=14,command=self.genBarcodes).grid(row=i,column=0)
        i+=1
        checkDate = Button(self.sideframe,text=' Check Dates ',command=self.checkConsigmentPeriods,width=14).grid(row=i,column=0)
        i+=1
        consTotals = Button(self.sideframe,text=' Consignor Totals  ', command=self.consignorTotals,width=14).grid(row=i,column=0)
        i+=1
        spc1=Label(self.sideframe,text=' ').grid(row=i,column=0,sticky=W)
        
        i+=1
        consButton=Button(self.sideframe,text='View Consignors',command=self.lookupConsignor,width=14).grid(row=i,column=0)
        i+=1        
        viewInventoryButton = Button(self.sideframe,text='  View Inventory  ',command=self.viewInventory,width=14).grid(row=i,column=0)
        i+=1
        searchByDescription=Button(self.sideframe,text= ' Keyword Search ',command=self.searchInventory,width=14).grid(row=i,column=0)
        i+=1
        spc2=Label(self.sideframe,text=' ').grid(row=i,column=0,sticky=W)
       
        i+=1
        addConsButton=Button(self.sideframe,text='  Add/Edit Consignor  ', command=self.addConsignor,width=14).grid(row=i,column=0)
        i+=1
        addInventoryButton=Button(self.sideframe,text='  Add Inventory  ',command=self.addInventory,width=14).grid(row=i,column=0)
        i+=1
        spc3=Label(self.sideframe,text=' ').grid(row=i,column=0,sticky=W)
        
        i+=1
        adjItemBtn = Button(self.sideframe,text='Set Item Price',width=14,command=self.adjPrice).grid(row=i,column=0)
        adjItemLabel = Label(self.sideframe,text='$').grid(row=i,column=1)
        adjItemEntry = Entry(self.sideframe,textvariable=self.adjItemPrice,width=8)
        adjItemEntry.grid(row=i,column=2)
        adjItemEntry.bind('<Return>',self.adjPrice)
        adjItemEntry.bind('<KP_Enter>',self.adjPrice)
        i+=1
        discItemBtn = Button(self.sideframe,text='Discount Item',command=self.discPrice,width=14).grid(row=i,column=0)
        discItemLabel = Label(self.sideframe,text='%').grid(row=i,column=1) 
        discItemEntry = Entry(self.sideframe,textvariable=self.discItemPrice,width=8)
        discItemEntry.grid(row=i,column=2)
        discItemEntry.bind('<Return>',self.discPrice)
        discItemEntry.bind('<KP_Enter>',self.discPrice)        
        i+=1
        adjCartBtn = Button(self.sideframe,text='Discount All',width=14,command=self.adjCart).grid(row=i,column=0)
        adjCartLabel = Label(self.sideframe,text='%').grid(row=i,column=1)
        adjCartEntry = Entry(self.sideframe,textvariable=self.applyDiscountPct,width=8)
        adjCartEntry.grid(row=i,column=2)
        adjCartEntry.bind('<Return>',self.adjCart)
        adjCartEntry.bind('<KP_Enter>',self.adjCart)               
        
        
root = Tk()            
gui = main(root)
root.mainloop()
